package com.jyxd.web.hiscz.service;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.jyxd.web.data.czhisdata.Operator;
import com.jyxd.web.data.patient.Patient;
import com.jyxd.web.hiscz.dto.BodyDto;
import com.jyxd.web.hiscz.dto.CodingDto;
import com.jyxd.web.hiscz.dto.RequestBodyDto;
import com.jyxd.web.hiscz.dto.ResponseDto;
import com.jyxd.web.hiscz.dto.checkout_report.Report.HandleDto;
import com.jyxd.web.hiscz.dto.patient.PatientVisitDto;
import com.jyxd.web.service.assessment.basic.MedOrderExecService;
import com.jyxd.web.service.czhis.OperatorService;
import com.jyxd.web.service.patient.PatientService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.jyxd.web.hiscz.Constant.HANDLE_BIG_TYPE_TRANSFER_OFFICES;
import static com.jyxd.web.hiscz.service.HisUtilService.hisResponse;
import static com.jyxd.web.hiscz.service.HisUtilService.isRequestEmpty;
import static com.jyxd.web.util.ExecuteUtil.errorIfEmpty;
import static com.jyxd.web.util.ExecuteUtil.getNullableOf;
import static com.jyxd.web.util.UUIDUtil.getUUID;

@Service
public class TransferOfficesHisService {

    private static Logger logger = LoggerFactory.getLogger(TransferOfficesHisService.class);

    @Autowired
    private PatientService patientService;

    @Autowired
    private HisUtilService hisUtilService;

    @Autowired
    private OperatorService operatorService;

    @Autowired
    private MedOrderExecService medOrderExecService;

    /**
     * 请求患者信息
     *
     * @param request
     * @return
     */
    public ResponseDto requestTransferOffices(RequestBodyDto request) {
        try {
            isRequestEmpty(request);
            logger.info("转科信息请求接收数据为：" + JSON.toJSONString(request));
            BodyDto body = request.getRequest().getBody();
            Patient patient = hisUtilService.getPatient(body);
            errorIfEmpty(patient, "转科患者不存在，转科失败");
            // 处理患者信息逻辑
            boolean isUpdatePatient = conductPatientVisit(patient, body.getPatientVisit());
            String message = isUpdatePatient ? "转科数据接收成功" : "转科数据接收错误";
            return new ResponseDto(hisResponse(request.getRequest().getHead(), "100", message));
        } catch (Exception e) {
            logger.info("转科数据逻辑数据处理出错：" + e.getMessage());
            return new ResponseDto(hisResponse(request.getRequest().getHead(), "100", e.getMessage()));
        }
    }

    /**
     * 处理患者信息逻辑
     */
    private boolean conductPatientVisit(Patient patient, PatientVisitDto patientVisit) {
        // 新增患者操作者信息
        saveHandle(patientVisit.getHandleList(), patient);
        // 处理转科逻辑
        return transferData(patientVisit, patient);
    }

    /**
     * 处理转科请求类型
     * 转科请求类型(0-转科,1-转icu,2-转产房,3-急观转住院,5-转床)
     *
     * @param
     * @param patient
     */
    private boolean transferData(PatientVisitDto patientVisit, Patient patient) {
        boolean isInDepartment = (patient.getStatus() != null && patient.getStatus() != -1);
        // 判断患者是否当前在科
        //boolean isInDepartment = Objects.nonNull(patient) && patient.getFlag() == 1 && patient.getStatus() == 1;
        // 获取转入科室名称
        String transferInName = getNullableOf(patientVisit.getPatientLocation().getDepartment(), CodingDto::getText, null);
        // 获取转入科室code
        String transferInCode = getNullableOf(patientVisit.getPatientLocation().getDepartment(), CodingDto::getIdentifier, null);
        // 获取转入科室床位
        String transferInBedCode = patientVisit.getPatientLocation().getBed();
        //添加测试转神经内科的功能
        //boolean isSevereCaseto = StringUtils.equals(transferInName, "神经内科");
        //if(!isSevereCaseto){
        //    patient.setBloodType("神经内科");
      //  }
        // 判断转入科室是否为重症科室
        boolean isSevereCase = StringUtils.equals(transferInName, "重症医学科") || StringUtils.equals(transferInCode, "068");
        logger.info("患者" + patient.getName() + "进行转科操作：转入科室为：" + transferInName + ";  转出科室为 ：" + patient.getToDepartmentCode());
        Date orderDate = medOrderExecService.queryDataByPatientName(patient.getId());
        if (isInDepartment) {  //判断是否到过重症
            //新增一条重症患者数据
            Patient newPatient = new Patient();
            BeanUtil.copyProperties(patient, newPatient, "id", "createTime", "toDepartmentCode");

            //如果通过医嘱赋值转入时间
            newPatient.setId(getUUID());
            newPatient.setFlag(0);
            newPatient.setStatus(-1);
            newPatient.setCreateTime(new Date());
            newPatient.setDepartmentCode(transferInName);
            newPatient.setInDepartmentCode(patient.getToDepartmentCode());
            // 设置转入病区code
            newPatient.setWardCode(getNullableOf(patientVisit.getPatientLocation().getWard(), CodingDto::getText, null));
            // 设置转入科室床位号
            newPatient.setBedCode(transferInBedCode);
            if(isSevereCase){
                newPatient.setEnterTime(orderDate == null ? patient.getVisitTime() : orderDate);
                newPatient.setFlag(1);
                newPatient.setStatus(1);
                // 如果转科患者为重症科室患者时，新增数据中心过敏信息
//                hisViewProduction.put(new HisViewDataDto(HIS_VIEW_EVENT_DC_HLCZJL_BZBWHL_GMS, newPatient));
                // 如果转科患者为重症科室患者时，新增或修改数据中心患者基本
//                hisViewProduction.put(new HisViewDataDto(HIS_VIEW_EVENT_DC_ICU_DAT_BRXXJLK, newPatient));
            }
            patientService.insert(newPatient, true);

            if(patient.getFlag() == 1){
                patient.setFlag(0); // 设置为出科科状态
                patient.setStatus(1); // 设置患者状态
                patient.setExitTime(new Date()); // 赋值转出科室时间
                patient.setExitType("转出科");
                // 赋值前科室（转出科室）名称
                patient.setToDepartmentCode(transferInName);
                patientService.update(patient);
                // 如果转出科患者为重症科室患者时，新增或修改数据中心患者基本
//                hisViewProduction.put(new HisViewDataDto(HIS_VIEW_EVENT_DC_ICU_DAT_BRXXJLK, patient));
            }
        } else {
            // 当前转入科室
            patient.setInDepartmentCode(patient.getDepartmentCode());
            patient.setDepartmentCode(transferInName);
            // 设置转入病区code
            patient.setWardCode(getNullableOf(patientVisit.getPatientLocation().getWard(), CodingDto::getText, null));
            // 设置转入科室床位号
            patient.setBedCode(transferInBedCode);
            // 判断如果转入科室为重症科的话
            if (isSevereCase) {
                patient.setFlag(1); // 设置为在科状态
                patient.setStatus(1); // 设置患者状态
                //patient.setEnterTime(new Date());
                //如果通过医嘱赋值转入时间
                patient.setEnterTime(orderDate==null? patient.getVisitTime():orderDate);
                // 如果转科患者为重症科室患者时，新增数据中心过敏信息
//                hisViewProduction.put(new HisViewDataDto(HIS_VIEW_EVENT_DC_HLCZJL_BZBWHL_GMS, patient));
                // 如果转科患者为重症科室患者时，新增或修改数据中心患者基本
//                hisViewProduction.put(new HisViewDataDto(HIS_VIEW_EVENT_DC_ICU_DAT_BRXXJLK, patient));
            }
            patientService.update(patient);
        }
        return true;
    }

    /**
     * 患者转移床位操作
     *
     * @param patientVisit
     * @param patient
     */
    private void transferBed(PatientVisitDto patientVisit, Patient patient) {
        if (Objects.isNull(patientVisit.getPatientLocation())) {
            logger.info("转入科室为空");
            return;
        }
        patient.setBedCode(patientVisit.getPatientLocation().getBed()); // 赋值新的床位号
        patient.setTransferBedTime(new Date()); // 设置转移床位时间
    }

    /**
     * 处理转ICU科室逻辑
     *
     * @param patientVisit
     * @param patient
     */
    private void transferICU(PatientVisitDto patientVisit, Patient patient) {
        if (Objects.isNull(patientVisit.getPatientLocation())) {
            logger.info("转入科室为空");
            return;
        }
        // 获取转入科室名称
        String transferInName = getNullableOf(patientVisit.getPatientLocation().getDepartment(), CodingDto::getText, null);
        // 获取转入科室code
        String transferInCode = getNullableOf(patientVisit.getPatientLocation().getDepartment(), CodingDto::getIdentifier, null);
        // TODO 获取到科室字典以后再做判断
        if (StringUtils.equals(transferInName, "重症医学科") || StringUtils.equals(transferInCode, "068")) {
            patient.setFlag(1); // 设置为在科状态
            patient.setStatus(1); // 设置患者状态
            // 设置转入科室code
            patient.setDepartmentCode(getNullableOf(patientVisit.getPatientLocation().getDepartment(), CodingDto::getIdentifier, null));
            // 设置转入病区code
            patient.setWardCode(getNullableOf(patientVisit.getPatientLocation().getWard(), CodingDto::getIdentifier, null));
            // 设置转入科室床位号
            patient.setBedCode(patientVisit.getPatientLocation().getBed());
            if (Objects.isNull(patientVisit.getPatientLocation())) {
                logger.info(patient.getName() + ": 转出科室为空");
                return;
            }
            // 赋值患者入科科室信息
            patient.setInDepartmentCode(getNullableOf(patientVisit.getPriorPatientLocation().getDepartment(), CodingDto::getText, null));
        }
    }

    /**
     * 接收数据为转出时
     */
    private void transferOut(PatientVisitDto patientVisit, Patient patient) {
        if (Objects.isNull(patientVisit.getPriorPatientLocation())) {
            logger.info("转出科室为空");
            return;
        }
        // 获取转出科室名称
        String transferOutName = getNullableOf(patientVisit.getPriorPatientLocation().getDepartment(), CodingDto::getText, null);
        // 获取转出科室code
        String transferOutCode = getNullableOf(patientVisit.getPriorPatientLocation().getDepartment(), CodingDto::getIdentifier, null);
        // TODO 获取到科室字典以后再做判断
        if (StringUtils.equals(transferOutName, "重症医学科") || StringUtils.equals(transferOutCode, "068")) {
            patient.setFlag(0); // 设置为出科状态
            patient.setStatus(1);
            patient.setToDepartmentCode(transferOutCode); // 设置转出科室编码为重症科室
            patient.setExitTime(new Date()); // 赋值转出科室时间
            patient.setExitType("转出科");
            if (Objects.isNull(patientVisit.getPatientLocation())) {
                logger.info(patient.getName() + ": 转入科室为空");
                return;
            }
            // 设置转入科室code
            patient.setDepartmentCode(getNullableOf(patientVisit.getPatientLocation().getDepartment(), CodingDto::getIdentifier, null));
            // 设置转入病区code
            patient.setWardCode(getNullableOf(patientVisit.getPatientLocation().getWard(), CodingDto::getIdentifier, null));
            // 设置转入科室床位号
            patient.setBedCode(patientVisit.getPatientLocation().getBed());
        }
    }


    /**
     * 新增操作者信息
     */
    private void saveHandle(List<HandleDto> handleList, Patient patient) {
        if (CollectionUtils.isEmpty(handleList)) {
            return;
        }
        handleList.forEach(handleDto -> {
            Operator operator = new Operator();
            operator.setId(getUUID());
            operator.setReTableId(patient.getId());
            operator.setBigType(HANDLE_BIG_TYPE_TRANSFER_OFFICES);
            operator.setCreateTime(new Date());
            if (Objects.nonNull(handleDto.getHandleBy())) {
                operator.setHandleIdNumber(handleDto.getHandleBy().getIDNumber());
                operator.setHandleName(handleDto.getHandleBy().getName());
            }
            operator.setTypeCode(getNullableOf(handleDto.getType(), CodingDto::getIdentifier, null)); // 操作code
            operator.setTypeName(getNullableOf(handleDto.getType(), CodingDto::getText, null));  // 操作名称
            operatorService.insert(operator);
        });
    }
}
